package org.javaforever.oville;

public class NarrowWord {
	private String varName;
	private byte [] narrowWord = new byte[4];
	public String getVarName() {
		return varName;
	}
	public void setVarName(String varName) {
		this.varName = varName;
	}
	
	public byte[] getNarrowWord() {
		return narrowWord;
	}
	public void setNarrowWord(byte[] narrowWord) {
		this.narrowWord = narrowWord;
	}
	public String toBinStr() throws ValidateException{
		StringBuilder sb = new StringBuilder();
		for (int i=0;i<4;i++) {
			byte bb = narrowWord[i];
			if (bb>127) bb -= 256;
			for (int j=7;j>=0;j--) {
				byte bit = (byte)((bb >>> j)%2);
				if (bit<0) bit += 2;
				//System.out.println(bit);
				sb.append(bit);
			}
		}
		return sb.toString();
	}
	
	public String toHexStr() throws ValidateException{
		String bin = this.toBinStr();
		StringBuilder sb = new StringBuilder();
		for (int i=0;i<8;i++) {
			sb.append(StringUtil.binDigToHex(bin.substring(i*4,(i+1)*4)));
		}
		return sb.toString();
	}	
	
	public static NarrowWord fromBinStr(String binStr) throws ValidateException{
		if (binStr.length() != 32) throw new ValidateException("Wrong narrowword bin string length!");
		for (int i=0;i<binStr.length();i++) {
			if (binStr.charAt(i)!='0'&&binStr.charAt(i)!='1'){
				throw new ValidateException("Wrong char in bin string!");
			}
		}
		NarrowWord w = new NarrowWord();
		byte [] bb = new byte[4];
		for (int i=0;i<binStr.length()/8;i++) {
			byte currentBb = eightBinToByte(binStr.substring(i*8, i*8+8));
			bb [i] = currentBb;
		}
		w.setNarrowWord(bb);
		return w;
	}
	
	public static byte eightBinToByte(String binStr) throws ValidateException{
		if (binStr.length() != 8) throw new ValidateException("Wrong size "+binStr.length()+" for bin string!");
		int result = Integer.parseInt(binStr, 2) % 256;
		if (result>=127) result -= 256;
		return (byte)result;
	}
	
	public long toLong() throws ValidateException{
		return Long.parseLong(this.toBinStr(),2);
	}
	
	public static NarrowWord fromLong(long val) {
		byte [] bytes = new byte[4];
		bytes[0] = (byte) (val / (256*256*256));
		bytes[1] = (byte) ((val / (256*256)) %256);
		bytes[2] = (byte) ((val / 256) %256);
		bytes[3] = (byte) (val % 256);
		NarrowWord nw = new NarrowWord();
		nw.setNarrowWord(bytes);
		return nw;
	}
	
	public boolean equals(NarrowWord nw) throws ValidateException{
		return this.toHexStr().equals(nw.toHexStr());
	}

	public static void main(String[] argv) throws ValidateException{
		NarrowWord w = new NarrowWord();
		w.setVarName("NarrowWord");
		byte [] bb = new byte[4];
		bb[0] = (byte)0b01010101;
		bb[1] = (byte)0b10101011>0?(byte)0b10101011:(byte)(0b10101011+256);
		w.setNarrowWord(bb);
		System.out.println(w.toBinStr());
		System.out.println(w.toHexStr());
	}
}
